/*
 * @Description: cesiumMapInit
 * @Author: ljt
 * @Date: 2022-12-29 15:55
 * @LastEditTime: 2022-12-29 15:55
 * @LastEditors: ljt
 */

import * as Cesium from "cesium";
import json from "@/assets/json/boundaryLine/NSboundaryLine.json";

const mapInit = (position: any, div: string = 'cesiumContainer', getPoint?: (args: any) => void) => {
    return new Promise((resolve, reject) => {
        Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI5ZjExMGM2NS1mMWQzLTRjNzEtODc1ZC0xMmQwYzNjZWE3ZDkiLCJpZCI6MTEwNjA0LCJpYXQiOjE2NjUzODc1ODB9.IoY4_TZQFr81KOFpT14H6aMTdbo90y0KbewQhu-wPx0'

        const mapOptions = {
            homeButton: false, //是否显示主页按钮
            sceneModePicker: false, //是否显示场景按钮
            baseLayerPicker: false, //是否显示图层选择控件
            navigationHelpButton: false, //导航帮助按钮
            selectionIndicator: false, //鼠标选择指示器
            animation: false, //是否创建动画小器件，左下角仪表
            timeline: false, //是否显示时间线控件
            geocoder: false, //是否显示地名查找控件
            fullscreenButton: true, //是否全屏按钮
            // shouldAnimate: true,
            infoBox: false,
            // terrainProvider: new Cesium.CesiumTerrainProvider({
            //     requestWaterMask: true, // 开启法向量
            //     requestVertexNormals: true // 开启水面特效
            // }),
            imageryProvider: new Cesium.UrlTemplateImageryProvider({
				url: '/layer/cesiumData/roadmap/china/{z}/{x}/{y}.png',
				// url: 'https://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetPurplishBlue/MapServer/tile/{z}/{y}/{x}'
				// url: 'https://webrd01.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}'
            }),
        }

        let viewer = new Cesium.Viewer(div, mapOptions);
		addImagery(viewer, '/layer/cesiumData/roadmap/nansha_rectangle/{z}/{x}/{y}.png')
		addImagery(viewer, '/layer/cesiumData/roadmap/nansha/{z}/{x}/{y}.png')
		
		viewer.scene.screenSpaceCameraController.maximumZoomDistance = 60000
        // @ts-ignore
        viewer._cesiumWidget._creditContainer.style.display = "none" // 去除版权信息

        // viewer.scene.globe.depthTestAgainstTerrain = true // 关闭地形

        Cesium.GeoJsonDataSource.load(json, {
            stroke: Cesium.Color.fromCssColorString('#011447'),
            fill: Cesium.Color.fromCssColorString('#000870').withAlpha(0.2),
            strokeWidth: 5,
            markerSymbol: '?'
        }).then(function (dataSource) {
            viewer.dataSources.add(dataSource).then(() => {
                viewer.scene.camera.setView({
                    // 经度 纬度 高度
                    destination: Cesium.Cartesian3.fromDegrees(
                        113.5000, 22.5000, 24800
                    ),
					orientation: {
						heading: Cesium.Math.toRadians(0.0),
						pitch: Cesium.Math.toRadians(-45.0),
						roll: 0.0
					}
                })
            });
        });

        viewer.scene.screenSpaceCameraController.tiltEventTypes = [
            Cesium.CameraEventType.RIGHT_DRAG, Cesium.CameraEventType.PINCH,
            {eventType: Cesium.CameraEventType.LEFT_DRAG, modifier: Cesium.KeyboardEventModifier.CTRL},
            {eventType: Cesium.CameraEventType.RIGHT_DRAG, modifier: Cesium.KeyboardEventModifier.CTRL}
        ];
        viewer.scene.screenSpaceCameraController.zoomEventTypes = [Cesium.CameraEventType.MIDDLE_DRAG, Cesium.CameraEventType.WHEEL, Cesium.CameraEventType.PINCH];

        let handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);

        // 鼠标移动获取坐标
        handler.setInputAction(function (movement: any) {
            //捕获椭球体，将笛卡尔二维平面坐标转为椭球体的笛卡尔三维坐标，返回球体表面的点
            var ellipsoid = viewer.scene.globe.ellipsoid;
            var cartesian = viewer.camera.pickEllipsoid(movement.endPosition, ellipsoid);
            if (cartesian) {
                //将笛卡尔三维坐标转为地图坐标（弧度）
                var cartographic = viewer.scene.globe.ellipsoid.cartesianToCartographic(cartesian);
                //将地图坐标（弧度）转为十进制的度数
                var lat = Cesium.Math.toDegrees(cartographic.latitude).toFixed(4);
                var lng = Cesium.Math.toDegrees(cartographic.longitude).toFixed(4);
                var height = (viewer.camera.positionCartographic.height / 1000).toFixed(2);
                position.value = lng + ", " + lat + ", " + height;
            }
        }, Cesium.ScreenSpaceEventType.MOUSE_MOVE)

        handler.setInputAction(function (event: any) {
            const {collection} = viewer.scene.pick(event.position);
            // 判断是否获取到了 pick
            collection && getPoint?.(event.position)
        }, Cesium.ScreenSpaceEventType.LEFT_CLICK)

        resolve({
            viewer,
            handler
        })
    })
}

/**
 * @description 生成CZML线的JSON数据
 * @param {number[]} cartographicDegrees 多组经度纬度高度 组成的坐标数组
 * @param {Number} type 类型 1为杆塔线路 2为台风线路
 * @return {Array} 所有线的CZML JSON数据
 */
export const getCzmlLine = (cartographicDegrees: number[], type: 1 | 2, lineType: string) => {
	let colors = {
		'110kV': [0, 243, 255, 255],
		'220kV': [50, 205, 50, 255],
		'500kV': [255, 127, 80, 255]
	}
    return [{
        "id": "document",
        "name": "CZML Geometries: Polyline",
        "version": "1.0"
    }, {
        "id": "fullLine",
        "name": "Yellow full line",
        "polyline": {
            "positions": {
                "cartographicDegrees": cartographicDegrees
            },
            "material": {
                "polylineOutline": {
                    "color": {
                        // "rgba": [0, 48, 210, 255]
						// let colors = {
						// 	'110kV': '#6bb2d6',
						// 	'220kV': '#000',
						// 	'500kV': '#000'
						// }
						// "rgba": [0, 243, 255, 255]
						"rgba": colors[lineType]
						// "rgba": [255, 127, 80, 255]
							
                    },
                    // "outlineColor": {
                    //     "rgba": [0, 66, 199, 255]
                    // },
                    // "outlineWidth": 7
                }
            },
            "width": 8,
            "clampToGround": true
        }
    }
    ];
}

/**
 * @description 添加CZML线实体到地图显示
 * @param {Array} polyLinePositions 由值为经纬度的对象组成的坐标数组（不含高度）
 * @param {Number} type 线路类型 1为杆塔线路 2为台风线路
 */
type Location = {
    latitude: string,
    longitude: string
}
export const creatLine = (viewer: Cesium.Viewer, polyLinePositions: Location[], type: 1 | 2, lineType: string) => {
    // 创建czml文件；得到czml数据源
    const lineGroup: any[] = []
    const polyLineSet = polyLinePositions.reduce((positionCollection, item) => {
        const values = Object.values(item)
        if (values.length < 3) { // @ts-ignore
            positionCollection = [...positionCollection, ...values, 0]
        }
        return positionCollection
    }, [])
    const czmlLine = getCzmlLine(polyLineSet, type, lineType);
    // 加载提供的URL或CZML对象，替换任何现有数据。
    const dataSourcePromise = Cesium.CzmlDataSource.load(czmlLine);
    viewer.dataSources.add(dataSourcePromise).then((data) => {
        lineGroup.push(data)
    });
    return lineGroup
    // 添加czml数据到三维球上
    // viewer.zoomTo(dataSourcePromise);
}

/**
 * @description 地图中绘制杆塔点
 * @param {object[]} tower 杆塔坐标二维数组
 * @param {Boolean} hasLine 是否需要绘制线路 用于区分所有杆塔和受损杆塔(受损杆塔不需要绘制线路)
 */
interface ITowerInfo {
    "id": string,
    "parentId": string,
    "weight": number,
    "name": string,
    "longitude": string,
    "latitude": string
}

export const lineInit = (viewer: Cesium.Viewer, towerInfos: ITowerInfo[], lineType: string) => {
    const color = Cesium.Color.fromCssColorString('#6bb2d6')
    const height = 0
    var pointCollection = new Cesium.PointPrimitiveCollection()
    // viewer.scene.primitives.add(new Cesium.PointPrimitiveCollection());

    const linePosition = towerInfos.reduce((towerPositions: any[], {
        latitude,
        longitude
    }: Location) => {

        // viewer.entities.add({
        //     name: "点",
        //     position: Cesium.Cartesian3.fromDegrees(+longitude, +latitude,
        //         height), // 点生成的位置
        //     point: {
        //         color: color, // 点颜色
        //         outlineColor: Cesium.Color.RED, // 点边框颜色
        //         pixelSize: size, // 点大小
        //         outlineWidth: 1, // 点边框大小
        //         disableDepthTestDistance: Number.POSITIVE_INFINITY, // 受地形遮挡
        //         heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, // 生成在地形表面
        //     }
        // });
        pointCollection.add({
            position: Cesium.Cartesian3.fromDegrees(+longitude, +latitude,
                height),
            color: color,
			distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 4000)
        });
        viewer.entities.add({
            name: '标点',
            position: Cesium.Cartesian3.fromDegrees(+longitude, +latitude,
                height),
            billboard:{
                image: new URL('@/assets/index/icon-ganta.png', import.meta.url).href,
                horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
                verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
                scale: .5,
                distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 4000)
            }
        })

        towerPositions = [...towerPositions, {
            longitude: +longitude,
            latitude: +latitude
        }]
        return towerPositions
    }, [])
    viewer.scene.primitives.add(pointCollection)
    return creatLine(viewer, linePosition, 1, lineType)
}

export const addImagery = (viewer: Cesium.Viewer, url: string, layerName?: string, id?: string): Cesium.UrlTemplateImageryProvider => {
    console.log('影像url', url);
    let imagery = new Cesium.UrlTemplateImageryProvider({
        url: url,
        tilingScheme: new Cesium.WebMercatorTilingScheme(),
        maximumLevel: 20
    });
    (imagery as any).layerName = layerName ? layerName : "image";
    (imagery as any).id = id;
    viewer.scene.imageryLayers.addImageryProvider(imagery);
    return imagery;
}

export const  addPnts = (viewer: Cesium.Viewer, url: string, layerName?: string, id?: string, pointSize?: number): Cesium.Cesium3DTileset => {
	console.log('点云url', url);
	let pnts = new Cesium.Cesium3DTileset({ url });
	(pnts as any).layerName = layerName ? layerName : "pnts";
	(pnts as any).id = id;
	pnts.style = new Cesium.Cesium3DTileStyle();
	(pnts.style as any).pointSize = pointSize ? pointSize : 3;
	pnts.maximumScreenSpaceError = 64.0;
	pnts.pointCloudShading.maximumAttenuation = 0;
	viewer.scene.primitives.add(pnts);
	return pnts;
}

export default mapInit